home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_351 / pdc / pdcsrc.lzh / A68k / Adirect.c < prev    next >
C/C++ Source or Header  |  1990-04-19  |  24KB  |  850 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*            MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*        Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*         Assembler directive processing - November 1, 1989        */
  8. /*                                    */
  9. /*   This program may be copied for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on all copies of the source code.  Copying for any other use   */
  12. /*   without the consent of the author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr. Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "A68kdef.h"
  25. #include "A68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), Instructions();
  29. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  30. extern int  ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
  31. extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
  32. extern char *AddName(), *GetField();
  33. extern struct SymTab *NextSym();
  34. extern struct SymTab **HashIt();
  35.  
  36.  
  37.  
  38. int ObjDir (dummy) int dummy;
  39. /* Generates Object Code for Assembler Directives. */
  40. {
  41.     register char *s, *t;
  42.     register int i, j;
  43.     int  oploc;
  44.     long templong;
  45.     char tempop[MAXLINE], delim;
  46.     struct SetFixup *sf;
  47.  
  48.     switch (Dir) {
  49.  
  50.     case Org:                        /* ORG, RORG */
  51.     PrntAddr = MakeHunk = TRUE;
  52.     FwdLim1     = FwdBranch;    /* Clear forward branch controls. */
  53.     FwdFixLimit = FwdBranchFix;
  54.     templong = GetValue (SrcOp, SrcLoc);
  55.     if (DefLine2 >= LineCount) {
  56.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  57.         break;
  58.     }
  59.     if (OpCode[0] == 'R') {                /* RORG */
  60.         if (Hunk2 != ABSHUNK) {
  61.         Error (SrcLoc, RelErr);    /* RORG needs an absolute value. */
  62.         break;
  63.         }
  64.     } else if (Hunk2 != CurrHunk) {
  65.         Error (SrcLoc, RelErr);    /* We can't ORG out of a hunk. */
  66.         break;
  67.     }
  68.  
  69.     if ((!Pass2 || (HunkType == HunkBSS))
  70.     && (templong < AddrCnt)    /* If we're ORGing to a lower address  */
  71.     && (AddrCnt > OrgHigh))    /*  and this is the highest we've been */
  72.         OrgHigh = AddrCnt;    /*  remember how far we got.           */
  73.  
  74.     AddrCnt = templong;    /* Update the location counter. */
  75.     OrgFlag = TRUE;        /* Indicate object fixups are needed. */
  76.     break;
  77.  
  78.     case Equ:                        /* EQU */
  79.     if (Label[0] == '\0')
  80.         Error (0, NeedLab);        /* We need a label. */
  81.     ObjSrc = GetValue (SrcOp, SrcLoc);
  82.     if (DefLine2 >= LineCount)
  83.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  84.     Src.Hunk = Hunk2;
  85.     PrntAddr = MakeHunk = TRUE;
  86.     break;
  87.  
  88.     case DC:                        /* DC */
  89.     if ((Size == Word) || (Size == Long))
  90.         AddrCnt = AddrBndW (AddrCnt);
  91.     s = Line + SrcLoc;
  92.     while (!isspace(*s) && (*s != '\0') && (*s != ';')) {
  93.         oploc = s - Line;
  94.         if (((*s == '\'') || (*s == '"'))    /* String */
  95.         && (Size == Byte)) {
  96.         delim = *s++;            /* Get the delimiter. */
  97.         while (1) {
  98.             if (*s == '\0') {        /* No closing delimiter */
  99.             Error (s-Line, NoStrEnd);
  100.             break;
  101.             }
  102.             if (*s == delim) {        /* End of string? */
  103.             if (*(++s) != delim)    /* Check next character. */
  104.                 break;        /* End of string */
  105.             }    /* Otherwise it's an apostrophe in the string. */
  106.             Src.Hunk = ABSHUNK;        /* Absolute value */
  107.             ObjString[nX++] = *s++;    /* Current character */
  108.         }
  109.         } else {            /* It's not a string constant. */
  110.         s = GetField (s, SrcOp);
  111.         ObjSrc = GetValue (SrcOp, oploc);    /* Value */
  112.         if ((Src.Hunk = Hunk2) != ABSHUNK) {    /* Hunk number */
  113.             templong = AddrCnt + nX;        /* Relocatable */
  114.             PutRel (templong, Hunk2, Size);
  115.         }
  116.         if (Size == 4) {
  117.             ObjString[nX++] = (ObjSrc >> 24) & 0x00FF;
  118.             ObjString[nX++] = (ObjSrc >> 16) & 0x00FF;
  119.         }
  120.         if (Size >= 2)
  121.             ObjString[nX++] = (ObjSrc >> 8) & 0x00FF;
  122.         ObjString[nX++] = ObjSrc & 0x00FF;
  123.         if (Size == 2)
  124.             templong = 0xFFFF0000L;
  125.         else if (Size == 1)
  126.             templong = 0xFFFFFF00L;
  127.         if (Size < 4)
  128.             if (((ObjSrc & templong) != 0)
  129.             && ((ObjSrc & templong) != templong))
  130.             Error (s-Line, SizeErr);
  131.         }
  132.         if (*s == ',')
  133.         s++;            /* Skip over separator. */
  134.     }
  135.     if ((!isspace(*s) && (*s != '\0') && (*s != ';'))
  136.     || (SrcLoc == 0))
  137.         Error (s-Line, OperErr);    /* Statement didn't end properly. */
  138.     AddrAdv = InstSize = nX;
  139.     PrntAddr = MakeHunk = TRUE;
  140.     break;
  141.  
  142.     case DS:                        /* DS */
  143.     if (DestLoc != 0) {
  144.         Error (DestLoc, OperErr);    /* Only one operand is allowed. */
  145.         PrntAddr = MakeHunk = TRUE;
  146.         break;
  147.     }
  148.     AddrAdv = GetValue (SrcOp, SrcLoc);
  149.     if (DefLine2 >= LineCount) {
  150.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  151.         AddrAdv = 0;
  152.     }
  153.     if (Hunk2 != ABSHUNK)
  154.         Error (SrcLoc, AbsReq);    /* Count must be absolute. */
  155.  
  156.     if (Size == Word) {        /* Words */
  157.         AddrCnt = AddrBndW (AddrCnt);
  158.         AddrAdv <<= 1;
  159.     }
  160.     if (Size == Long) {        /* Long words */
  161.         AddrCnt = AddrBndW (AddrCnt);
  162.         AddrAdv <<= 2;
  163.     }
  164.     if (Pass2 && (HunkType != HunkBSS)) {    /* If this isn't      */
  165.         templong = AddrAdv;            /*  a BSS hunk,       */
  166.         while (templong >= 4) {        /*  generate zeros    */
  167.         AppendSdata (0L, 4);        /*  to fill the area. */
  168.         templong -= 4;
  169.         }
  170.         if (templong > 0) {
  171.         i = templong;
  172.         AppendSdata (0L, i);
  173.         }
  174.     }
  175.     PrntAddr = MakeHunk = TRUE;
  176.     break;
  177.  
  178.     case Even:                        /* EVEN */
  179.     FwdLim1     = FwdBranch;    /* Clear forward branch controls. */
  180.     FwdFixLimit = FwdBranchFix;
  181.     AddrCnt = AddrBndW (AddrCnt);
  182.     PrntAddr = MakeHunk = TRUE;
  183.     break;
  184.  
  185.     case End:                        /* END */
  186.     if (Pass2)
  187.         if (SrcOp[0] != '\0')
  188.         EndAddr = GetValue (SrcOp, SrcLoc);
  189.         else
  190.         EndAddr = 0;
  191.     PrntAddr = MakeHunk = TRUE;
  192.     break;
  193.  
  194.     case Xdef:                        /* XDEF */
  195.     case Public:                    /* PUBLIC */
  196.     if (SFormat)
  197.         Error (OpLoc, NotSFmt);        /* Not in S-format */
  198.     s = Line + SrcLoc;
  199.     while (!isspace(*s) && (*s != '\0') && (*s != ';')) {
  200.         oploc = s - Line;
  201.         s = GetField (s, SrcOp);        /* Get a symbol. */
  202.         if (ReadSymTab (SrcOp)) {
  203.         if (!Pass2) {
  204.             if ((Sym->Flags & 0x61) == 0) {
  205.             Sym->Flags |= 2;    /* Set XDEF flag. */
  206.             if (OpCode[0] == 'P') {
  207.                 Sym->Flags |= 0x80;    /* It's defined as PUBLIC. */
  208.             }
  209.             }
  210.         } else {
  211.             if (Sym->Defn != LineCount)    /* If not PUBLIC->XREF */
  212.             AddRef (LineCount);    /*  it's a reference.  */
  213.             if (Sym->Defn == NODEF)
  214.             Error (oploc, Undef);    /* It never got defined. */
  215.             else if (Sym->Flags & 0x60)
  216.             Error (oploc, AddrErr);    /* Can't XDEF a register. */
  217.         }
  218.         } else if (!Pass2) {        /* It's not yet defined. */
  219.         if (OpCode[0] == 'P') {        /* Treat PUBLIC as XREF. */
  220.             AddSymTab (SrcOp, 0L, 0L ,LineCount, 0x81);
  221.             Sym->Hunk = ~((long) Sym->Nam);
  222.         } else {
  223.             AddSymTab (SrcOp, 0L, CurrHunk, NODEF, 2);    /* XDEF */
  224.         }
  225.         }
  226.         if (*s == ',')
  227.         s++;                /* Skip over separator. */
  228.     }
  229.     break;
  230.  
  231.     case Xref:                        /* XREF */
  232.     if (SFormat)
  233.         Error (OpLoc, NotSFmt);        /* Not in S-format */
  234.     s = Line + SrcLoc;
  235.     while (!isspace(*s) && (*s != '\0') && (*s != ';')) {
  236.         oploc = s - Line;
  237.         s = GetField (s, SrcOp);
  238.         if (Pass2) {
  239.         if (ReadSymTab (SrcOp)) {
  240.             if (Sym->Defn != LineCount) {
  241.             AddRef (LineCount);    /* Ignore extraneous XREF. */
  242.             }
  243.         }
  244.         } else {
  245.         if (!ReadSymTab    (SrcOp)) {    /* Only if not defined */
  246.             AddSymTab (SrcOp, 0L, 0L, LineCount, 1);
  247.             Sym->Hunk = ~((long) Sym->Nam);
  248.         }
  249.         }
  250.         if (*s == ',')
  251.         s++;            /* Skip over separator. */
  252.     }
  253.     break;
  254.  
  255.     case Page:                        /* PAGE */
  256.     if (Pass2 && (LineCount > 1))    /* Ignore PAGE at start of file. */
  257.         LnCnt = LnMax;        /* Resume on a new page. */
  258.     break;
  259.  
  260.     case DoList:                    /* LIST */
  261.     ListOff = FALSE;
  262.     if (!Pass2 && !SuppList && (IncStart != 0)) {
  263.         IncStart = 0;            /* We can't      */
  264.         if (SkipLim->Set1 != NULL) {    /*  skip this    */
  265.         SetFixLim = SkipLim->Set1;    /*  INCLUDE file */
  266.         SetFixLim++;            /*  in pass 2    */
  267.         }                    /*  (we must     */
  268.     }                    /*  list it).    */
  269.     break;
  270.  
  271.     case NoList:                    /* NOLIST */
  272.     ListOff = TRUE;
  273.     break;
  274.  
  275.     case Space:                        /* SPC */
  276.     if (Pass2 && !ListOff && !SuppList) {
  277.         if (SrcOp[0] != '\0')
  278.         j = GetValue (SrcOp, SrcLoc);    /* Amount to space */
  279.         else
  280.         j = 1;                /* Default to one line. */
  281.         for (i = 0; i < j; i++) {
  282.         if (LnCnt >= LnMax)
  283.             break;            /* Page overflow */
  284.         xputs (&List, "\n");        /* Space one line. */
  285.         }
  286.     }
  287.     break;
  288.  
  289.     case Title:                        /* TTL */
  290.     s = Line + SrcLoc;
  291.     t = TTLstring;
  292.     while (*s && (s < (TTLstring+MAXLINE)))
  293.         *t++ = *s++;        /* Get title string. */
  294.     *t = '\0';
  295.     if (LineCount > 1) {
  296.         LnCnt = LnMax;        /* Skip to a new page. */
  297.     } else {
  298.         if (Pass2) {
  299.         xputs (&List, TTLstring);
  300.         xputs (&List, "\n\n");
  301.         }
  302.         LnCnt += 2;            /* Don't skip at start of file. */
  303.     }
  304.     break;
  305.  
  306.     case Cnop:                        /* CNOP */
  307.     FwdLim1     = FwdBranch;    /* Clear forward branch controls. */
  308.     FwdFixLimit = FwdBranchFix;
  309.     i = TRUE;            /* "Error-free" flag */
  310.  
  311.     ObjSrc = GetValue (SrcOp, SrcLoc);
  312.     if (DefLine2 >= LineCount) {
  313.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  314.         i = FALSE;
  315.     }
  316.     if (Hunk2 != ABSHUNK) {
  317.         Error (SrcLoc, AbsReq);    /* Must be absolute! */
  318.         i = FALSE;
  319.     }
  320.  
  321.     ObjDest = GetValue (DestOp, DestLoc);
  322.     if (DefLine2 >= LineCount) {
  323.         Error (DestLoc, FwdRef);    /* Illegal forward reference */
  324.         i = FALSE;
  325.     }
  326.     if (Hunk2 != ABSHUNK) {
  327.         Error (DestLoc, AbsReq);    /* Must be absolute! */
  328.         i = FALSE;
  329.     }
  330.  
  331.     templong = ObjDest;
  332.     while ((templong > 0) && ((templong & 1) == 0))
  333.         templong >>= 1;        /* Shift out low-order zeros. */
  334.     if ((templong != 1) || (ObjDest == 1)) {
  335.         Error (DestLoc, OperErr);    /* DestOp must be a power of 2. */
  336.         i = FALSE;
  337.     }
  338.     if ((ObjSrc & 1) || (ObjSrc >= ObjDest)) {
  339.         Error (SrcLoc, OperErr);    /* SrcOp is odd or out of range. */
  340.         i = FALSE;
  341.     }
  342.  
  343.     if (i) {            /* If no errors so far... */
  344.         AddrCnt = AddrBndW (AddrCnt);
  345.         templong = (AddrCnt & ~(ObjDest-1)) + ObjSrc;
  346.         if (templong < AddrCnt)
  347.         templong += ObjDest;    /* We must advance to here. */
  348.         if ((templong - AddrCnt) < MAXLINE) {
  349.         nX = templong - AddrCnt;
  350.         for (j = 0; j < nX; ) {
  351.             ObjString[j++] = NOP / 256;
  352.             ObjString[j++] = NOP & 255;
  353.         }
  354.         AddrAdv = InstSize = nX;    /* Generate NOPs. */
  355.         PrntAddr = MakeHunk = TRUE;
  356.         } else {
  357.         Error (DestLoc, OperErr);    /* Too many NOPs */
  358.         }
  359.     }
  360.     break;
  361.  
  362.     case Include:                    /* INCLUDE */
  363.     if (Pass2                /* If we can skip */
  364.     && (SkipIdx < SkipLim)            /*  this INCLUDE  */
  365.     && (LineCount == SkipIdx->Start)) {    /*  file in pass  */
  366.         LineCount = SkipIdx->Finish;    /*  2, do so.     */
  367.         MacCount = SkipIdx->MCount;
  368.         if ((sf = SkipIdx->Set1) != NULL) {
  369.         while ((sf >= SetFixLim) && (sf->Sym != NULL)) {
  370.             (sf->Sym)->Val  = sf->Val;    /* Fix up SET symbols. */
  371.             (sf->Sym)->Hunk = sf->Hunk;
  372.             sf--;
  373.         }
  374.         }
  375.         SkipIdx++;
  376.         break;
  377.     }
  378.     if ((Quiet < 0) && (InF->UPtr == 0))
  379.         ShowLine (InF->Line);    /* Show where we are. */
  380.     s = Line + SrcLoc;
  381.     if ((*s == '"') || (*s == '\''))
  382.         s++;            /* Ignore quotes. */
  383.     t = tempop;
  384.     while (!isspace(*s)
  385.     && (*s != '"')
  386.     && (*s != '\'')
  387.     && (*s != '\0'))
  388.         *t++ = *s++;
  389.     *t = '\0';
  390.     if (InF->UPtr == 0) {
  391.         InF->Pos = lseek (In.fd, 0L, 1);
  392.         InF->Pos -= In.Lim-In.Ptr;    /* Position in outer file */
  393.     }
  394.     if (!OpenIncl (tempop, InclList)) {
  395.         Error (SrcLoc, NoIncl);    /* We couldn't open file. */
  396.         InclErrs = TRUE;
  397.         if (InF->UPtr == 0) {
  398.         In.fd = open (InF->NPtr, 0);
  399.         lseek (In.fd, InF->Pos, 0);
  400.         In.Ptr = In.Lim = In.Buf;
  401.         }
  402.         break;            /* Return to outer file. */
  403.     }
  404.     InFNum++;            /* Bump nesting level. */
  405.     if (--InF < LowInF)
  406.         LowInF = InF;
  407.     Heap2Space (strlen(tempop)+1);    /* Check for space. */
  408.     InF->UPtr = 0;            /* It's not a user macro. */
  409.     InF->NPtr = NextFNS;        /* New stack pointer */
  410.     strcpy (NextFNS, tempop);    /* File name */
  411.     NextFNS    += strlen (tempop) + 1;    /* Next available space */
  412.     if (NextFNS > High2)
  413.         High2 = NextFNS;        /* Set high-water mark. */
  414.     InF->NArg = -1;            /* Indicate it's not a macro. */
  415.     InF->Line = 0;            /* Clear line counter. */
  416.     InF->MCnt = MacCount;
  417.  
  418.     if (!Pass2 && (SuppList || ListOff) && (IncStart == 0)) {
  419.         s = (char *) SkipLim + sizeof (struct SkipEnt);
  420.         if (s <= (char *) SetFixLim) {
  421.         SkipLim->Set1 = NULL;    /* Save starting position */
  422.         IncStart = LineCount;    /*  in case we can skip   */
  423.         IncPtr = InF;        /*  this file in pass 2.  */
  424.         }
  425.     }
  426.     break;
  427.  
  428.     case Set:                        /* SET */
  429.     if (Label[0] == '\0')
  430.         Error (0, NeedLab);        /* Need a label */
  431.     ObjSrc = GetValue (SrcOp, SrcLoc);
  432.     if (DefLine2 >= LineCount)
  433.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  434.     Src.Hunk = Hunk2;
  435.     if (!ReadSymTab (Label))        /* Make a new entry. */
  436.         AddSymTab (Label, ObjSrc, Src.Hunk, LineCount, 4);
  437.     else if (Sym->Flags & 4) {        /* Re-SET the symbol. */
  438.         Sym->Val = ObjSrc;            /* SET value */
  439.         Sym->Hunk = Src.Hunk;        /* Hunk number */
  440.         Sym->Defn = LineCount;        /* Statement number */
  441.     }
  442.     PrntAddr = MakeHunk = TRUE;
  443.  
  444.     if (!Pass2 && (IncStart != 0)) {
  445.         if ((sf = SkipLim->Set1) != NULL) {
  446.         while (sf >= SetFixLim) {
  447.             if (sf->Sym != Sym) {
  448.             sf--;
  449.             } else {
  450.             sf->Val  = Sym->Val;    /* Update an        */
  451.             sf->Hunk = Sym->Hunk;    /*  existing entry. */
  452.             return (Set);
  453.             }
  454.         }
  455.         }
  456.         sf = SetFixLim;
  457.         sf--;
  458.         s = (char *) SkipLim + sizeof (struct SkipEnt);
  459.         if (s > (char *) sf) {
  460.         IncStart = 0;        /* There's no room for set symbol. */
  461.         if (SkipLim->Set1 != NULL) {
  462.             SetFixLim = SkipLim->Set1;
  463.             SetFixLim++;
  464.         }
  465.         } else {
  466.         if (SkipLim->Set1 == NULL)
  467.             SkipLim->Set1 = sf;    /* First SET symbol in INCLUDE */
  468.         sf->Sym  = Sym;
  469.         sf->Val  = Sym->Val;    /* Save SET symbol value */
  470.         sf->Hunk = Sym->Hunk;    /*  and hunk.            */
  471.         SetFixLim = sf;
  472.         }
  473.     }
  474.     break;
  475.  
  476.     case Macro:                        /* MACRO */
  477.     if (Label[0] == '\0')
  478.         Error (0, NeedLab);        /* Need a label */
  479.  
  480.     s = Label;
  481.     t = tempop;
  482.     *t++ = ' ';            /* Prepend name with a */
  483.     while (*s) {            /*  blank and convert  */
  484.         *t++ = toupper (*s);    /*  it to upper case.  */
  485.         s++;
  486.     }
  487.     *t = '\0';
  488.  
  489.     if (!Pass2) {            /* Pass 1 */
  490.         if (!ReadSymTab (tempop))        /* Save MACRO name. */
  491.         AddSymTab (tempop, 0L, 0L, LineCount, 8);
  492.         Sym->Hunk = (long) AddName(Line,1);    /* Save MACRO stmt. */
  493.     } else {            /* Pass 2 */
  494.         ReadSymTab (tempop);
  495.         if (Sym->Defn != LineCount) {
  496.         Error (LabLoc, DupMac);        /* Duplicate MACRO */
  497.         AddRef (LineCount);
  498.         }
  499.         WriteListLine (&List);        /* Echo MACRO. */
  500.     }
  501.  
  502.     i = 0;                /* IF nest counter */
  503.     while (1) {            /* Process macro body. */
  504.         if (LineParts (dummy)) {
  505.         Error (OpLoc, NoENDM);    /* Premature EOF */
  506.         i = 0;
  507.         break;
  508.         }
  509.         if ((i += CountNest (OpCode)) < 0) {
  510.         Error (OpLoc,ManyENDC);    /* Unmatched ENDC */
  511.         i = 0;
  512.         }
  513.         if (!Pass2)
  514.         AddName (Line, 2);    /* Store a line. */
  515.         if (strcmp (OpCode, "ENDM") == 0)
  516.         break;            /* Main program echoes ENDM. */
  517.         if (Pass2)
  518.         WriteListLine (&List);    /* Echo a line. */
  519.     }
  520.     if (i > 0)
  521.         Error (OpLoc, NoENDC);    /* ENDC is missing! */
  522.  
  523.     break;
  524.  
  525.     case IfEQ:                        /* IFEQ */
  526.     ObjSrc = GetValue (SrcOp, SrcLoc);
  527.     if (ObjSrc != 0)
  528.         SkipNest++;            /* Skip to the next ENDC. */
  529.     break;
  530.  
  531.     case IfNE:                        /* IFNE */
  532.     ObjSrc = GetValue (SrcOp, SrcLoc);
  533.     if (ObjSrc == 0)
  534.         SkipNest++;
  535.     break;
  536.  
  537.     case IfGT:                        /* IFGT */
  538.     ObjSrc = GetValue (SrcOp, SrcLoc);
  539.     if (ObjSrc <= 0)
  540.         SkipNest++;
  541.     break;
  542.  
  543.     case IfGE:                        /* IFGE */
  544.     ObjSrc = GetValue (SrcOp, SrcLoc);
  545.     if (ObjSrc < 0)
  546.         SkipNest++;
  547.     break;
  548.  
  549.     case IfLT:                        /* IFLT */
  550.     ObjSrc = GetValue (SrcOp, SrcLoc);
  551.     if (ObjSrc >= 0)
  552.         SkipNest++;
  553.     break;
  554.  
  555.     case IfLE:                        /* IFLE */
  556.     ObjSrc = GetValue (SrcOp, SrcLoc);
  557.     if (ObjSrc > 0)
  558.         SkipNest++;
  559.     break;
  560.  
  561.     case IfC:                        /* IFC */
  562.     if (strcmp (SrcOp, DestOp) != 0)
  563.         SkipNest++;
  564.     break;
  565.  
  566.     case IfNC:                        /* IFNC */
  567.     if (strcmp (SrcOp, DestOp) == 0)
  568.         SkipNest++;
  569.     break;
  570.  
  571.     case IfD:                        /* IFD */
  572.     if (ReadSymTab (SrcOp))
  573.         AddRef (LineCount);
  574.     if (DefLine2 > LineCount)
  575.         SkipNest++;
  576.     break;
  577.  
  578.     case IfND:                        /* IFND */
  579.     if (ReadSymTab (SrcOp))
  580.         AddRef (LineCount);
  581.     if (DefLine2 <= LineCount)
  582.         SkipNest++;
  583.     break;
  584.  
  585.     case EndC:                        /* ENDC */
  586.     break;                /* LineParts will take care of it. */
  587.  
  588.     case Section:                    /* SECTION */
  589.     tempop[0] = '\0';
  590.     s = Line + DestLoc + strlen (DestOp);    /* Check for flags. */
  591.     if (*s == ',') {
  592.         s++;
  593.         GetField (s, tempop);    /* Get specification. */
  594.     }
  595.     DoSection (SrcOp, SrcLoc, DestOp, DestLoc, tempop, j);
  596.     break;
  597.  
  598.     case CSeg:                        /* CODE */
  599.     DoSection (SrcOp, SrcLoc, "CODE", OpLoc, DestOp, DestLoc);
  600.     break;                /* Treat as SECTION. */
  601.  
  602.     case DSeg:                        /* DATA */
  603.     DoSection (SrcOp, SrcLoc, "DATA", OpLoc, DestOp, DestLoc);
  604.     break;                /* Treat as SECTION. */
  605.  
  606.     case BSS:                        /* BSS */
  607.     DoSection (SrcOp, SrcLoc, "BSS", OpLoc, DestOp, DestLoc);
  608.     break;                /* Treat as SECTION. */
  609.  
  610.     case Idnt:                        /* IDNT */
  611.     s = Line + SrcLoc;
  612.     if ((*s == '"') || (*s == '\''))
  613.         s++;            /* Ignore quotes. */
  614.     t = IdntName;
  615.     while (!isspace(*s)
  616.     && (*s != '"')
  617.     && (*s != '\'')
  618.     && (*s != '\0'))
  619.         *t++ = *s++;
  620.     *t = '\0';
  621.     break;
  622.  
  623.     case DCB:                        /* DCB */
  624.     if ((Size == Word) || (Size == Long))
  625.         AddrCnt = AddrBndW (AddrCnt);
  626.     DupFact = GetValue (SrcOp, SrcLoc);    /* Replication factor */
  627.     if (DefLine2 >= LineCount) {
  628.         Error (SrcLoc, FwdRef);    /* Illegal forward reference */
  629.         DupFact = 0;
  630.     }
  631.     if (Hunk2 != ABSHUNK) {
  632.         Error (SrcLoc, AbsReq);    /* Must be absolute! */
  633.         DupFact = 0;
  634.     }
  635.     ObjDest = GetValue (DestOp, DestLoc);    /* Value to replicate */
  636.     Dest.Hunk = Hunk2;
  637.     if (Size == 4) {
  638.         ObjString[nX++] = (ObjDest >> 24) & 0x00FF;
  639.         ObjString[nX++] = (ObjDest >> 16) & 0x00FF;
  640.     }
  641.     if (Size >= 2)
  642.         ObjString[nX++] = (ObjDest >> 8) & 0x00FF;
  643.     ObjString[nX++] = ObjDest & 0x00FF;
  644.  
  645.     AddrAdv = InstSize = nX;
  646.     if (Dest.Hunk != ABSHUNK) {        /* Relocatable */
  647.         templong = AddrCnt;
  648.         for (i = 0; i < DupFact; i++) {
  649.         PutRel (templong, Hunk2, Size);    /* Generate a relocation     */
  650.         templong += nX;            /*  entry for each constant. */
  651.         }
  652.     }
  653.     PrntAddr = MakeHunk = TRUE;
  654.     break;
  655.  
  656.     case Equr:                        /* EQUR */
  657.     if ((i = IsRegister (SrcOp, strlen (SrcOp))) < 0)
  658.         Error (SrcLoc, AddrErr);    /* Not a valid register. */
  659.     if (Label[0] == '\0')
  660.         Error (0, NeedLab);        /* Need a label */
  661.     else {
  662.         if (!ReadSymTab (Label))    /* Make a new entry. */
  663.         AddSymTab (Label, (long) i, 0L, LineCount, 0x20);
  664.         GotEqur = TRUE;        /* We have at least one EQUR. */
  665.     }
  666.     break;
  667.  
  668.     case Reg:                        /* REG */
  669.     if (Label[0] == '\0')
  670.         Error (0, NeedLab);        /* Need a label */
  671.     else {
  672.         if ((i = GetMultReg (SrcOp, SrcLoc)) == 0) {
  673.         Error (SrcLoc, OperErr);
  674.         } else {
  675.         if (!ReadSymTab    (Label)) {    /* Make a new entry. */
  676.             AddSymTab (Label, (long) i, 0L, LineCount, 0x40);
  677.             GotEqur = TRUE;        /* We have at least one EQUR. */
  678.         }
  679.         }
  680.     }
  681.     break;
  682.  
  683.     case Near:                        /* NEAR */
  684.     if (SrcOp[0] == '\0') {
  685.         SmallData = 4;        /* Default to register A4. */
  686.     } else {            /* Get register specification. */
  687.         SmallData = IsRegister (SrcOp, strlen (SrcOp)) - 8;
  688.         if ((SmallData < 0) || (SmallData > 6)) {
  689.         Error (SrcLoc,AddrErr);    /* It's not a valid register. */
  690.         SmallData = -1;        /* Disable small-data model. */
  691.         }
  692.     }
  693.     AnyNear    = TRUE;    /* Remember that we use small data somewhere. */
  694.     break;
  695.  
  696.     case Far:                        /* FAR */
  697.     SmallData = -1;        /* Reset small-data model flag. */
  698.     break;
  699.  
  700.     default:
  701.     break;
  702.     }
  703.  
  704.     return (Dir);
  705. }
  706.  
  707.  
  708.  
  709. DoSection (name, nameloc, type, typeloc, flags, flagloc)
  710. char *name, *type, *flags;
  711. int nameloc, typeloc, flagloc;
  712. /* Processes SECTION directive or equivalent. */
  713. {
  714.     static long HunkPos;    /* Seek address of start of section */
  715.     register char *s, *t;
  716.     long newflags, templong;
  717.     char tempop[MAXLINE];
  718.  
  719.     PrntAddr = TRUE;
  720.     if (SFormat)
  721.     Error (OpLoc, NotSFmt);    /* Not in S-format */
  722.  
  723.     if (HunkType != HunkNone) {
  724.     FwdLim1     = FwdBranch;    /* Clear forward branch controls. */
  725.     FwdFixLimit = FwdBranchFix;
  726.     }
  727.  
  728.     for (s = type; *s; s++)        /* Convert section type */
  729.     *s = toupper (*s);        /*  to upper case. */
  730.     if ((type[0] == '\0') || (strcmp (type, "CODE") == 0))
  731.     newflags = HunkCode;        /* Code section */
  732.     else if (strcmp (type, "DATA") == 0)
  733.     newflags = HunkData;        /* Data section */
  734.     else if (strcmp (type, "BSS") == 0)
  735.     newflags = HunkBSS;        /* BSS section */
  736.     else {
  737.     Error (typeloc, OperErr);    /* Invalid type */
  738.     strcpy (type, "CODE");
  739.     newflags = HunkCode;        /* Make it CODE. */
  740.     }
  741.     newflags <<= 16;    /* Shift to high-order 16 bits. */
  742.  
  743.     if (flags[0]) {
  744.     for (s = flags; *s; s++)        /* Convert flags */
  745.         *s = toupper (*s);            /*  to upper case. */
  746.     if (strcmp (flags, "CHIP") == 0)
  747.         newflags |= MEMF_CHIP;        /* CHIP memory */
  748.     else if (strcmp (flags, "FAST") == 0)
  749.         newflags |= MEMF_FAST;        /* FAST memory */
  750.     else
  751.         Error (flagloc, OperErr);        /* Invalid - ignore. */
  752.     }
  753.  
  754.     templong = (newflags & 0xFFFF0000) >> 16;
  755.     sprintf (tempop,"  %4x",HunkSeq++);    /* Make section name unique. */
  756.     s = name;
  757.     if ((*s == '"') || (*s == '\''))
  758.     s++;                /* Ignore quotes. */
  759.     t = tempop + 6;
  760.     while (!isspace(*s)
  761.     && (*s != '"')
  762.     && (*s != '\'')
  763.     && (*s != '\0'))
  764.     *t++ = *s++;            /* Concatenate section name. */
  765.     *t = '\0';
  766.  
  767.     if (ReadSymTab (tempop)) {        /* Scan for section name. */
  768.     if (HunkType == HunkNone) {
  769.         SectLine = 1;        /* Start of first section */
  770.     } else {
  771.         if (Pass2) {
  772.         AddRef (LineCount);
  773.         DumpSdata (&Srec);    /* Finish the previous hunk. */
  774.         if (!MakeHunk) {    /* If it was a null hunk, */
  775.             if (Srec.Ptr > Srec.Buf)    /* overwrite it.  */
  776.             write (Srec.fd, Srec.Buf, Srec.Ptr - Srec.Buf);
  777.             lseek (Srec.fd, HunkPos, 0);
  778.             Srec.Ptr = Srec.Buf;
  779.         }
  780.         } else {
  781.         AddrCnt = AddrBndL (AddrCnt);    /* Finish on long word. */
  782.         }
  783.         if (AddrCnt > OrgHigh)
  784.         Sect->Val = AddrCnt;    /* End of old section */
  785.         else
  786.         Sect->Val = OrgHigh;    /* We've ORGed higher. */
  787.         SectLine = LineCount;    /* Start of new section */
  788.     }
  789.     Sect = Sym;            /* Point to new section. */
  790.     AddrCnt = SectStart = Sym->Val;    /* Continuation */
  791.     OrgHigh = 0L;
  792.     OrgFlag = FALSE;
  793.     TempAddr = StartAddr = AddrCnt;
  794.     CurrHunk = Sym->Hunk & 0x0000FFFFL;    /* Hunk number */
  795.     HunkType = (Sym->Hunk & 0x3FFF0000L) >> 16;    /* Type */
  796.     HunkFlags = Sym->Hunk & 0xC0000000L;        /* Flags */
  797.     if (Pass2 && !SFormat) {        /* Start a new hunk. */
  798.         HunkPos = lseek (Srec.fd, 0L, 1);
  799.         HunkPos += Srec.Ptr - Srec.Buf;    /* It starts here. */
  800.         templong = HunkName;
  801.         xputl (&Srec, templong);
  802.         if (tempop[6])
  803.         DumpName (&Srec, &tempop[6], 0L);    /* Hunk name */
  804.         else
  805.         DumpName (&Srec, " ", 0L);
  806.         xputl (&Srec, HunkType | HunkFlags);    /* Hunk type */
  807.         LenPtr = Srec.Ptr;        /* Pointer to hunk length */
  808.         LenPos = lseek (Srec.fd, 0L, 1);
  809.         LenPos += LenPtr-Srec.Buf;    /* Hunk length goes here. */
  810.         xputl (&Srec, 0L);        /* For now, set it to zero. */
  811.     }
  812.     MakeHunk = FALSE;        /* We don't have anything yet. */
  813.     if (AnyNear && (CurrHunk > 1))
  814.         Error (OpLoc, ManySect);    /* Too many hunks for small data! */
  815.     return;
  816.     }
  817.  
  818.     AddrCnt = AddrBndL (AddrCnt);    /* Finish on long word bounary. */
  819.  
  820.     if (Pass2) {
  821.     Error (OpLoc, ManySect);    /* Table overflowed in pass 1! */
  822.     return;
  823.     }
  824.     if (NextHunk >= ABSHUNK)        /* Set up a new table entry. */
  825.     return;                /* Section table overflow */
  826.  
  827.     if (HunkType != HunkNone) {
  828.     if (AddrCnt > OrgHigh)
  829.         Sect->Val = AddrCnt;    /* End of old section */
  830.     else
  831.         Sect->Val = OrgHigh;    /* We've ORGed higher. */
  832.     SectLine = LineCount;        /* Starting line number */
  833.     } else {
  834.     SectLine = 1;            /* Start of first section */
  835.     }
  836.     AddrCnt = SectStart = OrgHigh = 0L;    /* Reset location counter. */
  837.     OrgFlag = FALSE;
  838.     TempAddr = StartAddr = AddrCnt;
  839.     HunkType = (newflags & 0x3FFF0000L) >> 16;    /* Type */
  840.     HunkFlags = newflags & 0xC0000000L;        /* Flags */
  841.     CurrHunk = NextHunk++;        /* Bump next hunk number. */
  842.     newflags |= CurrHunk;        /* Add hunk number to flags. */
  843.     AddSymTab (tempop, 0L, newflags, LineCount, 16);    /* New entry */
  844.     Sect = Sym;                /* Pointer to new entry */
  845.     MakeHunk = FALSE;            /* We don't have anything yet. */
  846.     if (AnyNear && (CurrHunk > 1))
  847.     Error (OpLoc, ManySect);    /* Too many hunks for small data! */
  848.     return;
  849. }
  850.